package cn.iocoder.yudao.module.eval.service.score;

import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.eval.controller.admin.score.vo.EvalScoreSummaryPageReqVO;
import cn.iocoder.yudao.module.eval.controller.admin.score.vo.EvalScoreSummarySaveReqVO;
import cn.iocoder.yudao.module.eval.dal.dataobject.score.EvalScoreSummaryDO;
import cn.iocoder.yudao.module.eval.dal.dataobject.score.EvalScoreRecordDO;
import cn.iocoder.yudao.module.eval.dal.mysql.score.EvalScoreSummaryMapper;
import cn.iocoder.yudao.module.eval.dal.mysql.score.EvalScoreRecordMapper;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.eval.enums.ErrorCodeConstants.*;

/**
 * 成绩汇总 Service 实现类
 *
 * @author 芋道源码
 */
@Service
@Validated
public class EvalScoreSummaryServiceImpl implements EvalScoreSummaryService {

    @Resource
    private EvalScoreSummaryMapper scoreSummaryMapper;
    
    @Resource
    private EvalScoreRecordMapper scoreRecordMapper;

    @Override
    public Long createScoreSummary(EvalScoreSummarySaveReqVO createReqVO) {
        // 插入
        EvalScoreSummaryDO scoreSummary = BeanUtils.toBean(createReqVO, EvalScoreSummaryDO.class);
        scoreSummary.setCalculationTime(LocalDateTime.now());
        scoreSummaryMapper.insert(scoreSummary);
        // 返回
        return scoreSummary.getId();
    }

    @Override
    public void updateScoreSummary(EvalScoreSummarySaveReqVO updateReqVO) {
        // 校验存在
        validateScoreSummaryExists(updateReqVO.getId());
        
        // 更新
        EvalScoreSummaryDO updateObj = BeanUtils.toBean(updateReqVO, EvalScoreSummaryDO.class);
        scoreSummaryMapper.updateById(updateObj);
    }

    @Override
    public void deleteScoreSummary(Long id) {
        // 校验存在
        validateScoreSummaryExists(id);
        // 删除
        scoreSummaryMapper.deleteById(id);
    }

    private void validateScoreSummaryExists(Long id) {
        if (scoreSummaryMapper.selectById(id) == null) {
            throw exception(SCORE_SUMMARY_NOT_EXISTS);
        }
    }

    @Override
    public EvalScoreSummaryDO getScoreSummary(Long id) {
        return scoreSummaryMapper.selectById(id);
    }

    @Override
    public PageResult<EvalScoreSummaryDO> getScoreSummaryPage(EvalScoreSummaryPageReqVO pageReqVO) {
        return scoreSummaryMapper.selectPage(pageReqVO);
    }

    @Override
    public List<EvalScoreSummaryDO> getScoreSummaryList(EvalScoreSummaryPageReqVO exportReqVO) {
        return scoreSummaryMapper.selectList(exportReqVO);
    }

    @Override
    public List<EvalScoreSummaryDO> getScoreSummaryListByPlanId(Long planId) {
        return scoreSummaryMapper.selectListByPlanId(planId);
    }

    @Override
    public void calculateScoreSummary(Long planId) {
        // 获取该计划下的所有评分记录
        List<EvalScoreRecordDO> scoreRecords = scoreRecordMapper.selectListByPlanId(planId);
        
        // 按参评人员分组
        Map<Long, List<EvalScoreRecordDO>> candidateScoreMap = scoreRecords.stream()
                .collect(Collectors.groupingBy(EvalScoreRecordDO::getCandidateId));
        
        // 为每个参评人员计算汇总成绩
        for (Map.Entry<Long, List<EvalScoreRecordDO>> entry : candidateScoreMap.entrySet()) {
            Long candidateId = entry.getKey();
            List<EvalScoreRecordDO> candidateScores = entry.getValue();
            
            // 计算总分和加权分
            BigDecimal totalScore = calculateTotalScore(candidateScores);
            BigDecimal weightedScore = calculateWeightedScore(candidateScores);
            
            // 判断是否合格
            boolean isQualified = weightedScore.compareTo(new BigDecimal("60")) >= 0;
            
            // 确定等级
            String gradeLevel = determineGradeLevel(weightedScore);
            
            // 检查是否已存在汇总记录
            EvalScoreSummaryDO existingSummary = scoreSummaryMapper.selectByPlanIdAndCandidateId(planId, candidateId);
            
            if (existingSummary != null) {
                // 更新现有记录
                existingSummary.setTotalScore(totalScore);
                existingSummary.setWeightedScore(weightedScore);
                existingSummary.setEvaluationResult(isQualified ? 1 : 0);
                existingSummary.setGradeLevel(gradeLevel);
                existingSummary.setCalculationTime(LocalDateTime.now());
                scoreSummaryMapper.updateById(existingSummary);
            } else {
                // 创建新记录
                EvalScoreSummaryDO newSummary = new EvalScoreSummaryDO();
                newSummary.setPlanId(planId);
                newSummary.setCandidateId(candidateId);
                newSummary.setTotalScore(totalScore);
                newSummary.setWeightedScore(weightedScore);
                newSummary.setEvaluationResult(isQualified ? 1 : 0);
                newSummary.setGradeLevel(gradeLevel);
                newSummary.setIsFinal(false);
                newSummary.setReviewStatus(0); // 待复核
                newSummary.setCalculationTime(LocalDateTime.now());
                scoreSummaryMapper.insert(newSummary);
            }
        }
    }

    @Override
    public void batchCalculateScoreSummary(List<Long> planIds) {
        for (Long planId : planIds) {
            calculateScoreSummary(planId);
        }
    }

    @Override
    public void reviewScoreSummary(Long id, String reviewResult, String reviewComments) {
        // 校验存在
        validateScoreSummaryExists(id);
        
        // 更新复核信息
        EvalScoreSummaryDO updateObj = new EvalScoreSummaryDO();
        updateObj.setId(id);
        updateObj.setReviewStatus("通过".equals(reviewResult) ? 1 : 2);
        updateObj.setReviewComments(reviewComments);
        updateObj.setReviewTime(LocalDateTime.now());
        updateObj.setIsFinal("通过".equals(reviewResult));
        scoreSummaryMapper.updateById(updateObj);
    }

    @Override
    public Object getScoreSummaryStatistics(Long planId) {
        List<EvalScoreSummaryDO> summaries = scoreSummaryMapper.selectListByPlanId(planId);
        
        long totalCount = summaries.size();
        long qualifiedCount = summaries.stream().filter(s -> s.getEvaluationResult() == 1).count();
        long excellentCount = summaries.stream().filter(s -> "优秀".equals(s.getGradeLevel())).count();
        long goodCount = summaries.stream().filter(s -> "良好".equals(s.getGradeLevel())).count();
        long passCount = summaries.stream().filter(s -> "合格".equals(s.getGradeLevel())).count();
        long failCount = summaries.stream().filter(s -> "不合格".equals(s.getGradeLevel())).count();
        
        return Map.of(
            "totalCount", totalCount,
            "qualifiedCount", qualifiedCount,
            "qualifiedRate", totalCount > 0 ? (double) qualifiedCount / totalCount * 100 : 0,
            "excellentCount", excellentCount,
            "goodCount", goodCount,
            "passCount", passCount,
            "failCount", failCount,
            "excellentRate", totalCount > 0 ? (double) excellentCount / totalCount * 100 : 0
        );
    }

    /**
     * 计算总分
     */
    private BigDecimal calculateTotalScore(List<EvalScoreRecordDO> scoreRecords) {
        return scoreRecords.stream()
                .map(EvalScoreRecordDO::getTotalScore)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
    }

    /**
     * 计算加权分
     */
    private BigDecimal calculateWeightedScore(List<EvalScoreRecordDO> scoreRecords) {
        // TODO: 根据科目权重计算加权分
        // 这里简化处理，直接取平均分
        if (scoreRecords.isEmpty()) {
            return BigDecimal.ZERO;
        }

        BigDecimal totalScore = calculateTotalScore(scoreRecords);
        return totalScore.divide(new BigDecimal(scoreRecords.size()), 2, java.math.RoundingMode.HALF_UP);
    }

    /**
     * 确定等级
     */
    private String determineGradeLevel(BigDecimal weightedScore) {
        if (weightedScore.compareTo(new BigDecimal("90")) >= 0) {
            return "优秀";
        } else if (weightedScore.compareTo(new BigDecimal("80")) >= 0) {
            return "良好";
        } else if (weightedScore.compareTo(new BigDecimal("60")) >= 0) {
            return "合格";
        } else {
            return "不合格";
        }
    }

}
